package com.zjl.spring.第09章_数据校验Validation.C_使用Validation注解;

import jakarta.validation.ConstraintViolation;
import jakarta.validation.constraints.*;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.constraints.Range;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Service;
import org.springframework.validation.BindException;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;

import java.math.BigDecimal;
import java.util.Set;

/**
 * @NotNull 限制必须不为null
 * @NotEmpty 只作用于字符串类型， 字符串不为空，并且长度不为0
 * @NotBlank 只作用于字符串类型， 字符串不为空，并且trim()后不为空串
 * @DecimalMax(value) 限制必须为一个不大于指定值的数字
 * @DecimalMin(value) 限制必须为一个不小于指定值的数字
 * @Digits(integer,fraction)	限制必须为一个小数，且整数部分的位数不能超过integer，小数部分的位数不能超过fraction
 * @Digits	验证 Number 和 String 的构成是否合法
 * @Max(value) 限制必须为一个不大于指定值的数字
 * @Min(value) 限制必须为一个不小于指定值的数字
 * @Size(max,min) 验证对象（Array,Collection,Map,String）长度是否在给定的范围之内
 * @Length(min,max) 验证字符串长度是否在给定的范围之内
 * @Email 验证注解的元素值是Email, 也可以通过正则表达式和flag指定自定义的email格式
 * @AssertFalse	限制必须为false
 * @AssertTrue	限制必须为true
 * @Past	限制必须是一个过去的日期,并且类型为java.util.Date
 * @Future	限制必须是一个将来的日期,并且类型为java.util.Date
 * @Pattern(value) 限制必须符合指定的正则表达式
 * @Range(max =3 , min =1)检查注释值是否位于（包括）指定的最小值和最大值之间
 * @Email	验证注解的元素值是Email，也可以通过正则表达式和flag指定自定义的email
 */
@Configuration//配置类
@ComponentScan(basePackages = "com.zjl.spring.第09章_数据校验Validation.C_使用Validation注解")//组件扫描
public class C_使用Validation注解 {

    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(C_使用Validation注解.class);

        ValidatorTest v = new ValidatorTest();

        //获取校验器
        MyValidator1 bean = context.getBean(MyValidator1.class);
        v.setQian("-96-");
        System.out.println("--------原生的校验---------------------");
        bean.validator1Check(v);//将校验对象放入校验器
        System.out.println("--------spring的校验---------------------");
        bean.validator2Check(v);

    }

    @Bean //自动注入 校验类
    public LocalValidatorFactoryBean validatorFactoryBean(){
        return new LocalValidatorFactoryBean();
    }
}
@Data
@NoArgsConstructor
@AllArgsConstructor
class ValidatorTest {

    //message  自定义出错信息
    @NotEmpty//限制字符串不为空，并且长度不为0
    @Length(min = 0,max = 200,message="字符过长")//限制字符长度必须在min到max之间
    @Digits(integer = 0, fraction = 0)
    @Range
    @Email
    private String name;

    @NotNull//限制必须不为null
    @Max(value = 200,message= "值太大了")//不大于指定值的数字
    @Min(0)//不小于指定值的数字
    private Integer age;

    @NotNull//限制必须不为null
    @DecimalMax(value = "20000.00")//不大于指定值的数字
    @DecimalMin(value = "0.00")//不小于指定值的数字
    private BigDecimal amt;

    @Pattern(regexp = "(-)?([1-9][0-9]*|0)([.][0-9]+)?",message = "不满足正则")
    private String qian;

}
@Service
class MyValidator1{
    @Autowired
    private jakarta.validation.Validator validator1;//原生校验

    public boolean validator1Check(ValidatorTest validatorTest){
        Set<ConstraintViolation<ValidatorTest>> validate = validator1.validate(validatorTest);
        for (ConstraintViolation<ValidatorTest> c:validate){
            System.out.println(c);
        }
        return validate.isEmpty();
    }

    @Autowired
    private org.springframework.validation.Validator validator2;//Spring 改过的校验
    public boolean validator2Check(ValidatorTest validatorTest){
        //Field error in object 'ValidatorTest' on field 'amt':...
        //这个string的值，对应着     'ValidatorTest' 这个
        BindException bindException = new BindException(validatorTest,"ValidatorTest");
        validator2.validate(validatorTest,bindException);
        System.out.println("错误的数量：" + bindException.getErrorCount());
        System.out.println(bindException.toString());
        return !bindException.hasErrors();
    }

}
